import type {AxiosInstance, AxiosResponse, InternalAxiosRequestConfig} from 'axios'
import axios, {type ResponseType} from 'axios'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import {$message} from "../tools/feedback.ts";
import type {UIFeedbackTypes} from "../types/morghulis.types.ts";
import {SYSTEM_KEY, useMorghulisAuthorize} from "./authorize.ts";
import {inject} from "vue";
import type {MorghulisOptions} from "../types/tool/channel.types.ts";

const {check, logout, $client, user, bearer} = useMorghulisAuthorize()


export function useMorghulisRequest() {

    const {baseURL, minioURL} = inject('options') as MorghulisOptions

    function getHttpRequest(auth?: boolean) {
        const instance = axios.create({baseURL})
        return wrap(instance, auth)
    }

    function getMinioRequest() {
        const instance = axios.create({baseURL: minioURL, responseType: 'arraybuffer'})
        return wrap(instance)
    }

    function all() {
        // ---
    }

    return {getHttpRequest, all}

}


function wrap(instance: AxiosInstance, auth?: boolean) {
    const {request, response} = instance.interceptors
    request.use((config) => beforeRequest(config, auth), onReject)
    response.use(beforeResponse, onReject)
    return instance
}

function beforeRequest(
    config: InternalAxiosRequestConfig, auth?: boolean
): InternalAxiosRequestConfig | Promise<any> {
    NProgress.start()
    config.headers[SYSTEM_KEY.CLIENT] = $client
    config.headers[SYSTEM_KEY.USER] = user()
    config.headers[SYSTEM_KEY.AUTH] = bearer()
    return config
}


function beforeResponse(
    response: AxiosResponse
): AxiosResponse | Promise<any> {
    NProgress.done()
    let {headers, data} = response
    const UID = headers[SYSTEM_KEY.USER]
    const AUTH = headers[SYSTEM_KEY.AUTH]
    const valid = (UID && AUTH && check(UID)) || (!UID && !AUTH)
    if (valid) {
        const {valar_message, valar_code} = headers
        if (valar_message) {
            const type: UIFeedbackTypes = valar_code
            $message[type](valar_message)
        }
        return data
    } else {
        const message = 'Unauthorized Request'
        $message.error(message)
        logout()
        return Promise.reject(new Error(message))
    }
}


function onReject(error: Error) {
    NProgress.done()
    return error
}
